package com.witherest.server.common.bean;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.text.StrSubstitutor;

/**
 * The Class Props.
 */
public class Props extends HashMap<String, String> {

	/** The Constant serialVersionUID. */
	private static final long serialVersionUID = 2211405016738281987L;


	/**
	 * Gets the group keys.
	 * 
	 * @param groupKey the group key
	 * @return the group keys
	 */
	public List<String> getGroupKeys(String groupKey) {
		List<String> result = new ArrayList<String>();
		for (String key : keySet()) {
			if (key.startsWith(groupKey))
				result.add(key);
		}
		return result;
	}

	/**
	 * Gets the string.
	 * 
	 * @param key the key
	 * @return the string
	 */
	public String getString(String key) {
		if (!containsKey(key)) {
			throw new IllegalArgumentException("Map key not found: " + key);
		}
		String result = get(key);
		return result;
	}

	/**
	 * Gets the string.
	 * 
	 * @param key the key
	 * @param def the def
	 * @return the string
	 */
	public String getString(String key, String def) {
		String result = get(key);
		if (result == null)
			result = def;
		return result;
	}

	/**
	 * Gets the int.
	 * 
	 * @param key the key
	 * @return the int
	 */
	public int getInt(String key) {
		String val = getString(key);
		int ret = Integer.parseInt(val);
		return ret;
	}

	/**
	 * Gets the int.
	 * 
	 * @param key the key
	 * @param def the def
	 * @return the int
	 */
	public int getInt(String key, int def) {
		String val = getString(key, "" + def);
		int ret = Integer.parseInt(val);
		return ret;
	}

	/**
	 * Gets the boolean.
	 * 
	 * @param key the key
	 * @return the boolean
	 */
	public boolean getBoolean(String key) {
		String val = getString(key);
		return Boolean.parseBoolean(val);
	}

	/**
	 * Gets the boolean.
	 * 
	 * @param key the key
	 * @param def the def
	 * @return the boolean
	 */
	public boolean getBoolean(String key, boolean def) {
		String val = getString(key, "" + def);
		return Boolean.parseBoolean(val);
	}

	/**
	 * Gets the long.
	 * 
	 * @param key the key
	 * @return the long
	 */
	public long getLong(String key) {
		String val = getString(key);
		long ret = Long.parseLong(val);
		return ret;
	}

	/**
	 * Gets the long.
	 * 
	 * @param key the key
	 * @param def the def
	 * @return the long
	 */
	public long getLong(String key, long def) {
		String val = getString(key, "" + def);
		long ret = Long.parseLong(val);
		return ret;
	}

	/**
	 * Gets the double.
	 * 
	 * @param key the key
	 * @return the double
	 */
	public double getDouble(String key) {
		String val = getString(key);
		double ret = Double.parseDouble(val);
		return ret;
	}

	/**
	 * Gets the double.
	 * 
	 * @param key the key
	 * @param def the def
	 * @return the double
	 */
	public double getDouble(String key, double def) {
		String val = getString(key, "" + def);
		double ret = Double.parseDouble(val);
		return ret;
	}
	
	/**
	 * Load.
	 * 
	 * @param inStream the in stream
	 */
	public void load(InputStream inStream) {
		Properties props = null;
		try {
			props = new Properties();
			props.load(inStream);
		}
		catch (FileNotFoundException e) {
			throw new RuntimeException(e);
		}
		catch (IOException e) {
			throw new RuntimeException(e);
		}
		finally {
			if (inStream != null) {
				IOUtils.closeQuietly(inStream);
			}
		}
		fromProperties(props);
	}

	/**
	 * Auto expand any ${variable} in expandProps using a lookupProps for existing variable definitions. This method will automatically
	 * search the System Properties space for lookup as well.
	 * <p>
	 * Note: There is no going back after you call this method!
	 */
	public void expandVariables() {
		StrSubstitutor substitutor = new StrSubstitutor(this);
		for (Map.Entry<String, String> entry : entrySet()) {
			String name = entry.getKey();
			String val = entry.getValue();
			if (val == null)
				continue;
			String newVal = substitutor.replace(val);
			if (!newVal.equals(val)) {
				this.put(name, newVal);
			}
		}
	}

	/**
	 * From properties.
	 * 
	 * @param props the props
	 */
	public void fromProperties(Properties props) {
		@SuppressWarnings({ "unchecked", "rawtypes" })
		Map<String, String> map = (Map) props;
		super.putAll(map);
	}
	
	/**
	 * Clone this map and return it as java.util.Properties
	 * 
	 * @return the properties
	 */
	@SuppressWarnings("unchecked")
	public Properties toProperties() {
		Properties properties = new Properties();
		properties.putAll((Map<String, String>) this.clone());
		return properties;
	}
}
